<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style type="text/css">
      .container {
      }

      .container .cart {
        width: 350px;
        /*background-color: lightgreen;*/
        margin: auto;
      }

      .container .title {
        background-color: lightblue;
        height: 40px;
        line-height: 40px;
        text-align: center;
        /*color: #fff;*/
      }

      .container .total {
        background-color: #ffce46;
        height: 50px;
        line-height: 50px;
        text-align: right;
      }

      .container .total button {
        margin: 0 10px;
        background-color: #dc4c40;
        height: 35px;
        width: 80px;
        border: 0;
      }

      .container .total span {
        color: red;
        font-weight: bold;
      }

      .container .item {
        height: 55px;
        line-height: 55px;
        position: relative;
        border-top: 1px solid #add8e6;
      }

      .container .item img {
        width: 45px;
        height: 45px;
        margin: 5px;
      }

      .container .item .name {
        position: absolute;
        width: 150px;
        top: 0;
        left: 55px;
        font-size: 16px;
      }

      .container .item .change {
        width: 100px;
        position: absolute;
        top: 0;
        right: 50px;
      }

      .container .item .change a {
        font-size: 20px;
        width: 30px;
        text-decoration: none;
        background-color: lightgray;
        vertical-align: middle;
      }

      .container .item .change .num {
        width: 40px;
        height: 25px;
      }

      .container .item .del {
        position: absolute;
        top: 0;
        right: 0px;
        width: 40px;
        text-align: center;
        font-size: 40px;
        cursor: pointer;
        color: red;
      }

      .container .item .del:hover {
        background-color: orange;
      }
    </style>
  </head>

  <body>
    <div id="app">
      <div class="container">
        <!-- <my-cart :list="goodsList"></my-cart> -->
        <my-cart></my-cart>
      </div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
      // 定义购物车组件
      Vue.component('MyCart', {
        components: {
          MyCartHeader: {
            props: {
              uname: String,
            },
            template: `
              <div class="title">{{ uname }}商品</div>
            `,
          },
          MyCartFooter: {
            props: {
              // total: Number,
              // 默认值配置
              total: { type: Number, default: 0 },
            },
            template: `
              <div class="total">
                <span>总价：{{ total }}</span>
                <button>结算</button>
              </div>
            `,
          },
          MyCartList: {
            props: {
              list: Array,
            },
            template: `
              <div>
                <template v-if="list === null">
                  加载中...
                </template>
                <template v-else-if="list.length === 0">
                  暂无数据
                </template>
                <template v-else>
                  <div class="item" v-for="(v, i) in list" :key="v.id">
                    <img :src="v.imgSrc" />
                    <div class="name">
                      <span>{{ v.name }}</span>
                      <span>{{ v.price }}</span>
                    </div>
                    <div class="change">
                      <a href="" @click.prevent="sub(v.id)">－</a>
                      <input type="text" class="num" :value="v.count" @input="onInputOfCount($event, v)" @blur="onBlurOfCount($event, v)" />
                      <a href="" @click.prevent="add(v.id)">＋</a>
                    </div>
                    <div class="del" @click="del(v.id)">×</div>
                    <!-- <div class="del" @click="delByIndex(i)">×</div> -->
                  </div>
                </template>
              </div>
            `,
            methods: {
              onBlurOfCount(e, goods) {
                // 在失去焦点时，如果输入框是空的，那么就重置为上一个有效的数量
                // e.target：就是这个 input 元素 dom 对象
                let val = e.target.value.trim();
                if (val === '') {
                  e.target.value = goods.count;
                }
              },
              onInputOfCount(e, goods) {
                // 去掉输入框中的前后空格
                let val = e.target.value.trim();
                // 如果输入的是空字符串，那么就直接over
                if (val === '') {
                  return;
                }

                // 如果不是空字符串，则将其转换成整数
                val = parseInt(val);
                console.log(val, 'val');
                // 如果这个整数是 NaN 或者 小于 1，则不需要通知父组件
                if (isNaN(val) || val < 1) {
                  console.log('不需要通知父组件');
                  // 输入的数字非法，将输入框中的值重置为之前的数量（可以让用户看不到自己输入的字母以及非法的数量）
                  e.target.value = goods.count;
                } else {
                  console.log('通知父组件修改数量');

                  this.$emit('change-count', { id: goods.id, count: val });
                  // 输入的数字合法（因为有可能 用户输入的是  123abdefgt，通过parseInt 转换时，也能够得到一个正确的整数123，所以还是能看到字母，那么就需要重置）
                  e.target.value = val;
                }
              },
              // 减少数量
              sub(id) {
                this.$emit('sub', id);
              },
              // 添加数量
              add(id) {
                this.$emit('add', id);
              },
              delByIndex(i) {
                this.$emit('del-by-index', i);
              },
              // 删除商品（List组件）
              del(id) {
                console.log(id, '要删除的商品id');
                // 在哪里删？  我直接操作 list 删掉吗？
                this.$emit('del', id); // 触发自定义事件del,通知父组件删除该id的商品
              },
            },
          },
        },
        template: `
          <div class="cart">
            <my-cart-header uname="张三"></my-cart-header>
            <my-cart-list 
              :list="goodsList" 
              @del="del" 
              @del-by-index="delByIndex"
              @add="add"
              @sub="sub"
              @change-count="changeCount"
            ></my-cart-list>
            <my-cart-footer :total="total"></my-cart-footer>
          </div>
        `,
        data() {
          return { goodsList: null };
        },
        computed: {
          total() {
            // 方案一：
            // let sum = 0;
            // if (this.goodsList === null) {
            //   return sum;
            // }
            // this.goodsList.forEach((v) => {
            //   sum += v.price * v.count;
            // });
            // console.log('计算出的总价为：', sum);
            // return sum;

            // 方案二：
            if (this.goodsList === null) {
              return 0;
            }
            return this.goodsList.reduce((sum, v) => sum + v.price * v.count, 0);
          },
        },
        methods: {
          // 当数量改变时（直接在输入框中输入）
          changeCount(e) {
            console.log('获取到了事件对象', e);
            const goods = this.goodsList.find((v) => v.id === e.id);
            goods.count = e.count;
          },
          sub(id) {
            const goods = this.goodsList.find((v) => v.id === id);
            // 什么时候能减？只有当数量大于等于2时
            if (goods.count >= 2) {
              goods.count--;
            }
          },
          add(id) {
            // 根据id找出该商品
            const goods = this.goodsList.find((v) => v.id === id);
            // 将其数量+1
            goods.count++;
          },
          delByIndex(i) {
            console.log(i, '拿到了要删除的索引');
            // 假设删除商品需要发送ajax请求，并且请求比较慢，需要3秒钟
            setTimeout(() => {
              this.goodsList.splice(i, 1);
            }, 3000);

            // 模拟，在这删除商品的3秒内，又添加了两个商品
            setTimeout(() => {
              this.goodsList.unshift({ id: 6, imgSrc: 'img/e.jpg', name: '测试商品1', count: 0, price: 5000 });
              this.goodsList.unshift({ id: 7, imgSrc: 'img/e.jpg', name: '测试商品2', count: 0, price: 5000 });
            }, 1000);
          },
          // 删除商品（MyCart组件）
          del(id) {
            console.log(id, '爸爸收到了，准备删除');
            // 方案一：
            // filter 留下符合条件的，剔除不符合条件的，属于非变异方法，不会影响原数组，会返回一个新数组
            // this.goodsList = this.goodsList.filter((v) => v.id !== id);

            // 方案二：
            const index = this.goodsList.findIndex((v) => v.id === id);
            this.goodsList.splice(index, 1);
          },
        },
        mounted() {
          // 页面一加载，就要发送 ajax 请求，获取商品列表数据
          setTimeout(() => {
            this.goodsList = [
              { id: 1, imgSrc: 'img/a.jpg', name: 'TCL彩电', count: 12, price: 1000 },
              { id: 2, imgSrc: 'img/b.jpg', name: '机顶盒', count: 1, price: 2000 },
              { id: 3, imgSrc: 'img/c.jpg', name: '海尔冰箱', count: 1, price: 3000 },
              { id: 4, imgSrc: 'img/d.jpg', name: '小米手机', count: 1, price: 4000 },
              { id: 5, imgSrc: 'img/e.jpg', name: 'PPTV电视', count: 1, price: 5000 },
            ];
          }, 300);
        },
      });

      var vm = new Vue({
        el: '#app',
        data: {},
      });
    </script>
  </body>
</html>
